package com.sy.notice.biz.eventmanage.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.watch.WatchMonitor;
import cn.hutool.core.io.watch.Watcher;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sy.notice.biz.eventdefine.entity.EventTask;
import com.sy.notice.biz.eventmanage.core.ScheduledManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.Map;

/**
 * @author 舒祥
 * @date 2022-01-14 21:14
 * @desc
 */
@Component
@Slf4j(topic = "syslog")
public class FileChangedListener implements ApplicationRunner {

    @Value("${event.file.path:/home/sy/event.json}")
    private String path;

    @Autowired
    private ScheduledManager scheduledManager;

    /**
     * 文件改动-->重新部署
     *
     * @throws Exception
     */
    public void reloadTask() {
        try {
            String result = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8);
            Map map = JSON.parseObject(result, Map.class);
            List<JSONObject> events = (List) map.get("events");
            //全部取消
            scheduledManager.cancelAllScheduledFuture();
            for (JSONObject event : events) {
                EventTask eventTask = JSON.parseObject(JSON.toJSONString(event), EventTask.class);
                try {
                    //scheduledManager.cancelScheduledFuture(eventTask.getKey());
                    scheduledManager.addScheduledFuture(eventTask);
                } catch (Exception e) {
                    log.error("addScheduledSource error", e);
                }
            }
        } catch (Throwable e) {
            log.error("error", e);
        }
    }


    /**
     * 配置文件变动监听;
     *
     * @author:舒祥
     * @createTime: 2022/11/16 17:09
     */
    @Override
    public void run(ApplicationArguments args) {
        File file = FileUtil.file(path);
        WatchMonitor watchMonitor = WatchMonitor.create(file, WatchMonitor.ENTRY_MODIFY);
        watchMonitor.setWatcher(new Watcher() {
            @Override
            public void onCreate(WatchEvent<?> watchEvent, Path path) {
                log.info("onCreate");
            }

            @Override
            public void onModify(WatchEvent<?> event, Path currentPath) {
                Object obj = event.context();
                log.info("修改：{}-> {}", currentPath, obj);
                reloadTask();
            }

            @Override
            public void onDelete(WatchEvent<?> watchEvent, Path path) {
                log.info("onDelete");
            }

            @Override
            public void onOverflow(WatchEvent<?> watchEvent, Path path) {
                log.info("onOverflow");
            }
        });
        watchMonitor.start();
        // this.md5Old = DigestUtils.md5DigestAsHex(new FileInputStream(path));
       /*
        //WatchService监听文件变化;
       WatchService watchService = FileSystems.getDefault().newWatchService();
        Paths.get("/home/sy/").register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY},
                SensitivityWatchEventModifier.LOW);
        while(true){
            WatchKey key = watchService.take();
            List<WatchEvent<?>> watchEvents = key.pollEvents();
            for (WatchEvent<?> event : watchEvents) {
                if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
                    //事件可能lost or discarded
                    continue;
                }
                // 返回触发事件的文件或目录的路径（相对路径）
                Path fileName = (Path) event.context();
                System.out.println("文件更新: " + fileName);
            }
            key.reset();
        }*/
    }
}